using System;

namespace Think.Problems
{
    public class Foundation
    {
        private readonly CardSuit _suit;
        private int _value = 0;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="a_suit">Foundation suit.</param>
        /// <exception cref="ArgumentNullException">Thrown if "<paramref name="a_suit"/>" is null.</exception>
        public Foundation(CardSuit a_suit)
        {
            _suit = a_suit;
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="a_other">Other foundation.</param>
        protected Foundation(Foundation a_other)
        {
            _suit = a_other._suit;
            _value = a_other.Value;
        }

        /// <summary>
        /// Foundation Suit.
        /// </summary>
        public CardSuit Suit 
        {
            get { return _suit; }
        }

        /// <summary>
        /// Rank value of the card on the top of this foundation.
        /// </summary>
        public int Value
        {
            get { return _value; }
        }

        /// <summary>
        /// Whether this foundation is complete.
        /// </summary>
        public bool IsComplete
        {
            get { return _value >= 13; }
        }

        /// <summary>
        /// Top card of this foundation.
        /// </summary>
        public string TopCard
        {
            get
            {
                if (_value <= 0)
                    return null;

                return Card.Create(_suit, _value);
            }
        }

        /// <summary>
        /// Set the given card (<paramref name="a_card"/>) on top of this foundation.
        /// </summary>
        /// <param name="a_card">Card to set.</param>
        /// <exception cref="ArgumentNullException">Thrown if "<paramref name="a_card"/>" is null.</exception>
        public void Set(string a_card)
        {
            if (!CanSet(a_card))
                throw new InvalidOperationException("Cannot set the given card ('" + a_card + "')");

            _value++;
        }

        /// <summary>
        /// Determine whether the given card (<paramref name="a_card"/>) can be set on top of this foundation.
        /// </summary>
        /// <param name="a_card">Card to set.</param>
        /// <returns>True if card can be set.</returns>
        /// <exception cref="ArgumentNullException">Thrown if "<paramref name="a_card"/>" is null.</exception>
        public bool CanSet(string a_card)
        {
            #region Argument Validation

            if (a_card == null)
                throw new ArgumentNullException("a_card");

            #endregion

            if (Card.Suit(a_card) != _suit)
                return false;

            if (Card.RankValue(a_card) != _value + 1)
                return false;

            return true;
        }

        /// <summary>
        /// Clone this foundation.
        /// </summary>
        /// <returns>Clone of foundation.</returns>
        public Foundation Clone()
        {
            return new Foundation(this);
        }
    }
}